////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

Log.print('service module: stisimo');

// Στο παρόν περιέχονται δομές και μέθοδοι που αφορούν στο στήσιμο
// της παρτίδας στον server. Οι διαδικασία έχει ως εξής:
//
// 1.	Ο παίκτης θέτει κάποια παράμετρο της παρτίδας από τον client
//	κάνοντας κλικ σε κάποιο πλήκτρο του control panel, ή με κάποιον
//	άλλον τρόπο.
// 2.	Στον client δεν γίνεται καμία αλλαγή στην παρτίδα, παρά αποστέλλεται
//	αίτημα στον Node server στο οποίο περιγράφεται η συγκεκριμένη
//	ενέργεια.
// 3.	Ο server επεξεργάζεται το αίτημα και αφού ελέγξει διάφορα θέματα
//	ασφαλείας κλπ, εκτελεί την ενέργεια στην database και στο σκηνικό
//	του εκτελώντας τη σχετική μέθοδο (οι μέθοδοι αυτές είναι κοινές σε
//	server και clients και βρίσκονται στο "common/stisimo.js").
// 4.	Εφόσον όλα τα παραπάνω πήγαν καλά, δημιουργείτα κίνηση η οποία
//	περιγράφει την συγκεκριμένη ενέργεια και μέσω της κίνησης αυτής
//	ενημερώνονται όλοι οι clients (μαζί και ο client που δρομολόγησε
//	αρχικά την ενέργεια).
// 5.	Με την παραλαβή της σχετικής κίνησης επιτελείται στον κάθε client
//	η ίδια διαδικασία που επιτελεστηκε στον server, επομένως θα έχουμε
//	τις ίδιες αλλαγές στα επί μέρους σκηνικά των clients.
//
// Όλα τα παραπάνω εντάσσονται σε αντικείμενο "Service.stisimo".

Service.stisimo = {};

// Η function "stisimoExec" κάνει τους ελέγχους που αφορούν στην ύπαρξη συνεδρίας για τον
// παίκτη που κάνει την αλλαγή και ότι σε αυτή τη συνεδρία ο παίκτης εμφανίζεται ως
// παίκτης σε κάποιο τραπέζι. Όλες οι αλλαγές θα αφορούν σε αυτό το τραπέζι. Εφόσον
// ο έλεγχος δεν δείξει προβλήματα στο αίτημα, καλείται η function που δίδεται ως
// δεύτερη παράμετρος.

var stisimoExec = function(nodereq, callback) {
	if (nodereq.isvoli()) return;
	if (nodereq.oxiTrapezi()) return;
	if (nodereq.sinedria.oxiPektis() && nodereq.pektis.oxiEpoptis())
		return nodereq.end('Δεν είστε παίκτης του τραπεζιού');

	//  Κλείνουμε το αίτημα, αλλά περνάμε τις url παραμέτρους στην
	// function εξυπηρέτησης, μήπως και χρειαστούμε κάποια παράμετρο.
	// Παράλληλα περνάμε τη συνεδρία και το τραπέζι του παίκτη που
	// αιτείται την αλλαγή.

	nodereq.end();
	if (callback) callback(nodereq.url, nodereq.sinedria, nodereq.trapezi);
}

// Η function "trparamQuery" διευκολύνει στο κομμάτι της ενημέρωσης των
// παραμέτρων του τραπεζιού στην database. Πράγματι, κάθε αλλαγή παραμέτρου
// αντανακλά σε αντίστοιχη αλλαγή στην database και μάλιστα πρώτα επιχειρούμε
// την αλλαγή στην database και κατόπιν προχωρούμε στην αλλαγή σκηνικού και
// στην ενημέρωση των clients.

var trparamQuery = function(conn, trapezi, value, param, timi) {
	if (timi === undefined) timi = 'ΝΑΙ';
	return value ?
		"REPLACE INTO `trparam` (`trapezi`, `param`, `timi`) VALUES (" +
			trapezi.kodikos + ", " + conn.escape(param) + ", " + conn.escape(timi) + ")"
	:
		"DELETE FROM `trparam` WHERE `trapezi` = " + trapezi.kodikos +
			" AND `param` = " + conn.escape(param);
}

// Τελευταίο βήμα στην εφαρμογή οποιασδήποτε αλλαγής είναι η εισαγωγή σχετικής
// κίνησης στο transaction log. Από εκεί θα ενημερωθούν όλοι οι clients για την
// αλλαγή που συνετελέσθη στην database και στο σκηνικό του server. Οι κινήσεις
// αυτές περιέχουν δύο properties: το είδος της κίνησης (ένα κωδικό string) και
// το login name του παίκτη που αιτήθηκε την αλλαγή. Η διαχείριση των κινήσεων
// αυτών γίνεται από μεθόδους που βρίσκονται στο "prefadoros/kinisi.js" και
// προσομοιάζουν στις μεθόδους του παρόντος.

var kinisiAdd = function(idos, sinedria, enimerosi) {
	(new Kinisi({
		'?': idos,
		'p': sinedria.pektis
	})).kinisiAdd(enimerosi);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

// Η μέθοδος "roloi" επιτελεί κυκλική εναλλαγή των παικτών του
// τραπεζιού.

Service.stisimo.roloi = function(nodereq) {
	stisimoExec(nodereq, function(url, sinedria, trapezi) {
		var tok = Prefadoros.stisimo.roloiPrep(trapezi, sinedria);
		var conn = DB.connection();
		conn.transaction(function(conn) {
			Service.stisimo.roloi1(conn, sinedria, trapezi, tok);
		});
	});
}

Service.stisimo.roloi1 = function(conn, sinedria, trapezi, tok) {
	var query = "UPDATE `trapezi` SET " +
		"`pektis1` = " + conn.escape(tok.pektis1) + ", " +
		"`apodoxi1` = '" + (tok.apodoxi1 ? 'ΝΑΙ' : 'ΟΧΙ') + "', " +
		"`pektis2` = " + conn.escape(tok.pektis2) + ", " +
		"`apodoxi2` = '" + (tok.apodoxi2 ? 'ΝΑΙ' : 'ΟΧΙ') + "', " +
		"`pektis3` = " + conn.escape(tok.pektis3) + ", " +
		"`apodoxi3` = '" + (tok.apodoxi3 ? 'ΝΑΙ' : 'ΟΧΙ') + "' " +
		"WHERE `kodikos` = " + trapezi.kodikos;
	conn.connection.query(query, function(err, res) {
		if (err) {
			conn.rollback();
			Log.sqlError(query);
			return;
		}

		Service.stisimo.roloi2(conn, sinedria, trapezi, tok);
	});
}

// Η κυκλική εναλλαγή των παικτών έχει μια σημαντική παρενέργεια: αν το τραπέζι
// είναι ιδιόκτητο, τότε αίρεται το ιδιοκτησιακό καθεστώς, καθώς είναι ο άρχων
// που δρομολόγησε την εναλλαγή και με τον τρόπο αυτόν θα περάσει την ιδιοκτησία
// στον προηγούμενο παίκτη, πράγμα που δεν είναι επιθυμητό.

Service.stisimo.roloi2 = function(conn, sinedria, trapezi, tok) {
	var query = "DELETE FROM `trparam` WHERE `trapezi` = " + trapezi.kodikos + " " +
		"AND `param` = " + conn.escape('ΙΔΙΟΚΤΗΤΟ');
	conn.query(query, function(conn) {
		conn.commit();
		Prefadoros.stisimo.roloi(trapezi, tok);
		kinisiAdd('RLI', sinedria);
	});
}

// Η μέθοδος "diataxi" εναλλάσσει μεταξύ τους τούς άλλους δύο παίκτες, ενώ αυτός
// που εκτελεί την αλλαγή παραμένει στη θέση του. Η αλλαγή διάταξης εκτελείται
// μόνον εφόσον οι θέσεις που θα εναλλαγούν δεν είναι και οι δύο κενές.

Service.stisimo.diataxi = function(nodereq) {
	stisimoExec(nodereq, function(url, sinedria, trapezi) {
		var tok = Prefadoros.stisimo.diataxiPrep(trapezi, sinedria);
		// Αν δεν υπάρχει παίκτης στις εναλλασσόμενες θέσεις
		// δεν κάνουμε καμία περαιτέρω ενέργεια.
		if (!tok) return;

		var conn = DB.connection();
		var query = "UPDATE `trapezi` SET " +
			"`pektis1` = " + conn.escape(tok.pektis1) + ", " +
			"`apodoxi1` = '" + (tok.apodoxi1 ? 'ΝΑΙ' : 'ΟΧΙ') + "', " +
			"`pektis2` = " + conn.escape(tok.pektis2) + ", " +
			"`apodoxi2` = '" + (tok.apodoxi2 ? 'ΝΑΙ' : 'ΟΧΙ') + "', " +
			"`pektis3` = " + conn.escape(tok.pektis3) + ", " +
			"`apodoxi3` = '" + (tok.apodoxi3 ? 'ΝΑΙ' : 'ΟΧΙ') + "' " +
			"WHERE `kodikos` = " + trapezi.kodikos;
		conn.connection.query(query, function(err, res) {
			if (err) {
				Log.sqlError(query);
				return;
			}

			conn.free();
			Prefadoros.stisimo.diataxi(trapezi, tok);
			kinisiAdd('DTX', sinedria);
		});
	});
}

Service.stisimo.kasa = function(nodereq) {
	stisimoExec(nodereq, function(url, sinedria, trapezi) {
		var tok = Prefadoros.stisimo.kasaPrep(trapezi, sinedria.thesi);
		var conn = DB.connection();
		var query = trparamQuery(conn, trapezi, (tok.kasa != 50), 'ΚΑΣΑ', tok.kasa);
		conn.query(query, function(conn) {
			conn.free();
			Prefadoros.stisimo.kasa(trapezi, tok);
			kinisiAdd('KAS', sinedria);
		});
	});
}

Service.stisimo.kasaAlagi = function(nodereq) {
	var kasa, conn, query, kasa;

	if (nodereq.isvoli()) return;
	if (nodereq.oxiTrapezi()) return;
	if (nodereq.sinedria.oxiPektis() && nodereq.pektis.oxiEpoptis())
		return nodereq.end('Δεν είστε παίκτης του τραπεζιού');
	if (!nodereq.url.hasOwnProperty('alagi')) return nodereq.end('Ακαθόριστη αλλαγή κάσας');
	if (isNaN(nodereq.url.alagi)) return nodereq.end('Απροσδιόριστη αλλαγή κάσας');

	kasa = nodereq.trapezi.kasa() + parseInt(nodereq.url.alagi);
	if (kasa < 0) return nodereq.end('Έχετε ήδη την ελάχιστη κάσα');
	if (kasa > 100) return nodereq.end('Μήπως να παίζατε καινούρια παρτίδα;');
	nodereq.end();

	conn = DB.connection();
	query = trparamQuery(conn, nodereq.trapezi, (kasa != 50), 'ΚΑΣΑ', kasa);
	conn.query(query, function(conn) {
		conn.free();
		nodereq.trapezi.trparam['ΚΑΣΑ'] = kasa;
		new Kinisi({
			'?': nodereq.url.alagi > 0 ? 'K+' : 'K-',
			'p': nodereq.sinedria.pektis,
			't': nodereq.trapezi.kodikos,
			'k': kasa,
		}).kinisiAdd();
	});
}

Service.stisimo.paso = function(nodereq) {
	stisimoExec(nodereq, function(url, sinedria, trapezi) {
		var tok = Prefadoros.stisimo.pasoPrep(trapezi, sinedria);
		var conn = DB.connection();
		var query = trparamQuery(conn, trapezi, tok.paso, 'ΠΑΣΟ');
		conn.query(query, function(conn) {
			conn.free();
			Prefadoros.stisimo.paso(trapezi, tok);
			kinisiAdd('PPP', sinedria);
		});
	});
}

Service.stisimo.asoi = function(nodereq) {
	stisimoExec(nodereq, function(url, sinedria, trapezi) {
		var tok = Prefadoros.stisimo.asoiPrep(trapezi, sinedria);
		var conn = DB.connection();
		var query = trparamQuery(conn, trapezi, !tok.asoi, 'ΑΣΟΙ', 'ΟΧΙ');
		conn.query(query, function(conn) {
			conn.free();
			Prefadoros.stisimo.asoi(trapezi, tok);
			kinisiAdd('ACE', sinedria);
		});
	});
}

Service.stisimo.filiki = function(nodereq) {
	stisimoExec(nodereq, function(url, sinedria, trapezi) {
		var tok = Prefadoros.stisimo.filikiPrep(trapezi, sinedria);
		var conn = DB.connection();
		var query = trparamQuery(conn, trapezi, tok.filiki, 'ΦΙΛΙΚΗ');
		conn.query(query, function(conn) {
			conn.free();
			Prefadoros.stisimo.filiki(trapezi, tok);
			kinisiAdd('LRN', sinedria);
		});
	});
}

Service.stisimo.postel = function(nodereq) {
	stisimoExec(nodereq, function(url, sinedria, trapezi) {
		var tok = Prefadoros.stisimo.postelPrep(trapezi, sinedria);
		var conn = DB.connection();
		var query = trparamQuery(conn, trapezi, tok.postel != 'ΚΑΝΟΝΙΚΟ', 'ΤΕΛΕΙΩΜΑ', tok.postel);
		conn.query(query, function(conn) {
			conn.free();
			Prefadoros.stisimo.postel(trapezi, tok);
			kinisiAdd('PTL', sinedria);
		});
	});
}

Service.stisimo.idioktito = function(nodereq) {
	stisimoExec(nodereq, function(url, sinedria, trapezi) {
		var tok = Prefadoros.stisimo.idioktitoPrep(trapezi, sinedria);
		var conn = DB.connection();
		var query = trparamQuery(conn, trapezi, tok.idioktito, 'ΙΔΙΟΚΤΗΤΟ');
		conn.query(query, function(conn) {
			conn.free();
			Prefadoros.stisimo.idioktito(trapezi, tok);
			kinisiAdd('IDK', sinedria);
		});
	});
}

Service.stisimo.idiotikotita = function(nodereq) {
	stisimoExec(nodereq, function(url, sinedria, trapezi) {
		var tok, conn, query;

		tok = Prefadoros.stisimo.idiotikotitaPrep(trapezi);
		conn = DB.connection();
		query = trparamQuery(conn, trapezi, tok.prive, 'ΠΡΙΒΕ');
		conn.query(query, function(conn) {
			var theatis, s;

			conn.free();
			Prefadoros.stisimo.idiotikotita(trapezi, tok);
			if (!tok.prive) return kinisiAdd('PRV', sinedria);

			(new Kinisi({
				'?': 'PRV',
				'p': sinedria.pektis,
			})).kinisiAdd(false);

			// Θα αποβάλλουμε τώρα όλους τους θεατές που δεν είναι
			// προσκεκλημένοι.

			for (theatis in trapezi.theatis) {
				if (trapezi.isProskeklimenos(theatis)) continue;

				// Διαγράφουμε τον απρόσκλητο θεατή από τη λίστα
				// θεατώ του τραπεζιού.

				trapezi.theatisDel(theatis);

				// Αν υπάρχει σχετική συνεδρία, θα πρέπει να
				// ενημερωθούν τα στοιχεία θέσης της συνεδρίας.

				s = Skiniko.isSinedria(theatis);
				if (s) s.trapeziExodos();

				// Ενημερώνουμε τους clients ότι ο θεατής έχει
				// αποβληθεί.

				(new Kinisi({
					'?': 'EX',
					'p': theatis,
				})).kinisiAdd(false);
			}

			Skiniko.sinedriaEnimerosi();
		});
	});
}

Service.stisimo.klisto = function(nodereq) {
	stisimoExec(nodereq, function(url, sinedria, trapezi) {
		var tok = Prefadoros.stisimo.klistoPrep(trapezi);
		var conn = DB.connection();
		var query = trparamQuery(conn, trapezi, tok.klisto, 'ΑΝΟΙΚΤΟ', 'ΟΧΙ');
		conn.query(query, function(conn) {
			conn.free();
			Prefadoros.stisimo.klisto(trapezi, tok);
			kinisiAdd('KLT', sinedria);
		});
	});
}

Service.stisimo.epetiaki = function(nodereq) {
	stisimoExec(nodereq, function(url, sinedria, trapezi) {
		var tok = Prefadoros.stisimo.epetiakiPrep(trapezi);
		var conn = DB.connection();
		var query = trparamQuery(conn, trapezi, tok.epetiaki, 'ΕΠΕΤΕΙΑΚΗ');
		conn.query(query, function(conn) {
			conn.free();
			Prefadoros.stisimo.epetiaki(trapezi, tok);
			kinisiAdd('EPT', sinedria);
		});
	});
}

Service.stisimo.apodoxi = function(nodereq) {
	stisimoExec(nodereq, function(url, sinedria, trapezi) {
		var apodoxi, conn, query, thesi, nai = 0;

		if (trapezi.isDianomi()) return;

		apodoxi = trapezi.apodoxi(sinedria.thesi);
		conn = DB.connection();
		query = 'UPDATE `trapezi` SET `apodoxi' + sinedria.thesi + '` = ' +
			conn.escape(apodoxi ? 'ΟΧΙ' : 'ΝΑΙ') + ' WHERE `kodikos` = ' + trapezi.kodikos;
		conn.query(query, function(conn) {
			conn.free();
			Prefadoros.stisimo.apodoxi(trapezi, sinedria);
			kinisiAdd('APD', sinedria);

			// Αν το τραπέζι έχει διανομές, τότε η αποδοχή/επαναδιαπραγμάτευση
			// δεν έχει καμία επίπτωση στο τραπέζι.

			if (trapezi.isDianomi()) return;

			// Το τραπέζι δεν έχει διανομές, επομένως θα πρέπει να δούμε αν
			// με τη συγκεκριμένη αποδοχή θα πρέπει να εκκινήσει το παιχνίδι.

			for (thesi in Prefadoros.thesiValid) {
				if (trapezi.apodoxi(thesi)) nai++;
			}
			if (nai >= 3) trapezi.neaDianomi(1);
		});
	});
}
